home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / tc_menu.arc / TC-MENU.C < prev   
Text File  |  1988-11-19  |  23KB  |  960 lines

  1. /*
  2. **  TC-MENU.C
  3. **
  4. **  Turbo C version of James Pinson's Lattice C program PULLDOWN.C
  5. **
  6. **  I edited his program to suit my indentation style, cleaned up the
  7. **  code in a few places, and made adjustments for Turbo C.
  8. **
  9. **  Compile with   tcc -K tc-menu
  10. **  or in TC with O/C/C/Default char type...Unsigned
  11. **  Ignore the three compiler warnings.
  12. **
  13. **  If you get snow on your monitor, type in    tc-menu s    to prevent
  14. **  the program from using direct screen writes.
  15. **
  16. **    -- Scott Houck
  17. */
  18.  
  19. #include <stdio.h>
  20. #include <ctype.h>
  21. #include <dos.h>
  22. #include <conio.h>
  23. #include <mem.h>
  24.  
  25. #define BLACK   0       /* These are for color cards */
  26. #define BLUE    1
  27. #define GREEN   2
  28. #define CYAN    3
  29. #define RED     4
  30. #define MAGENTA 5
  31. #define BROWN   6
  32. #define WHITE   7
  33. #define L_BLUE  9       /* Light-blue foreground only */
  34. #define L_GREEN 10      /* Light-green foreground only */
  35. #define YELLOW  14
  36. #define IWHITE  15      /* Intense-white foreground only */
  37.  
  38. #define UNDERLINE 1     /* These are for monochrome cards */
  39. #define NORMAL    7
  40. #define HI_INTEN  15
  41. #define REVERSE   112
  42.  
  43. #define TRUE  1
  44. #define FALSE 0
  45.  
  46. unsigned int page;        /* extern decl. for functions */
  47. unsigned int attribute;
  48. unsigned int mon_type;
  49. char wrt_meth = 'f';
  50.  
  51. #define  NU_MAIN 5        /* number of main menu options */
  52. #define  NU_SUB  5        /* number of sub menu options  */
  53.  
  54. int menu();
  55. int pull_down();
  56. void make_help();
  57. void make_inst();
  58. void mono_help();
  59. void demo();
  60. void help();
  61. void gotoxy();
  62. int wherexy();
  63. void d_page();
  64. void win_save();
  65. int set_color();
  66. void clear_window();
  67. void box();
  68. int what_mon();
  69. void cls();
  70. void make_window();
  71. int cursor();
  72. void print();
  73. void dos_prt();
  74. void fast_write();
  75. int get_key();
  76.  
  77.  
  78. struct menu_str           /* change this if you need more options */
  79. {
  80.    char *head;
  81.    char *body[NU_SUB];
  82.    void (*fun1)();
  83.    void (*fun2)();
  84.    void (*fun3)();
  85.    void (*fun4)();
  86.    void (*fun5)();
  87. };
  88.  
  89.  
  90. /*-----------*/
  91. /*  M A I N  */
  92. /*-----------*/
  93.  
  94. main(argc, argv)
  95. int argc;
  96. char **argv;
  97. {
  98.    extern unsigned int page;
  99.    extern unsigned int attribute;
  100.    extern unsigned int mon_type;
  101.  
  102.    int hi_attr, nor_attr;
  103.  
  104.    static struct menu_str m_menu[NU_MAIN] =
  105.    {
  106.       "   File   ",     /*  The first menu option */
  107.       "   Dir      ",   /*  Menu sub options */
  108.       "   Load     ",
  109.       "   Save     ",
  110.       "   dElete   ",
  111.       "   Path     ",
  112.       demo,             /* The functions each sub-option call */
  113.       demo,
  114.       demo,             /* these all call the same fake function */
  115.       demo,
  116.       demo,
  117.  
  118.       "   fiNd   ",     /* The second menu option */
  119.       " All-words  ",
  120.       " First-word ",
  121.       "\0",
  122.       "\0",             /* space filler for unused option names */
  123.       "\0",
  124.       demo,
  125.       demo,
  126.       0,                /* unused function pointer */
  127.       0,
  128.       0,
  129.  
  130.       "   Configure   ",    /* The third option */
  131.       " Modem ",
  132.       " Screen ",
  133.       " Printer ",
  134.       "\0",
  135.       "\0",
  136.       demo,
  137.       demo,
  138.       demo,
  139.       0,
  140.       0,
  141.  
  142.       "        Output       ",    /* The fourth menu option */
  143.       "  Screen  ",
  144.       "  Printer ",
  145.       "  Disk    ",
  146.       "  Modem   ",
  147.       "\0",
  148.       demo,
  149.       demo,
  150.       demo,
  151.       demo,
  152.       0,
  153.  
  154.  
  155.       " Help ",                       /* The fifth option */
  156.       " Instant help (really works) ",
  157.       "\0",
  158.       "\0",
  159.       "\0",
  160.       "\0",
  161.       help,
  162.       0,
  163.       0,
  164.       0,
  165.       0,
  166.    };
  167.  
  168.  
  169.    /* was a slow write requested? */
  170.    if (tolower(*argv[1]) == 's')
  171.       wrt_meth = 's';
  172.  
  173.    page = 0;
  174.    mon_type = what_mon();
  175.  
  176.    if (mon_type == 1)             /* Find out if you have a color card */
  177.       {
  178.       hi_attr = set_color(BLACK, CYAN); /* and set attributes accordingly */
  179.       nor_attr = set_color(WHITE, BLACK);
  180.       }
  181.    else
  182.       {
  183.       hi_attr = REVERSE;
  184.       nor_attr = NORMAL;
  185.       }
  186.  
  187.    attribute = nor_attr;
  188.    cursor(0);               /* hide cursor */
  189.    win_save('s');
  190.    cls();
  191.  
  192.    if (mon_type == 1)
  193.       make_help();
  194.  
  195.    make_inst();          /* Show instructions */
  196.  
  197.    menu(m_menu, NU_MAIN, NU_SUB, hi_attr, nor_attr);
  198.  
  199.    win_save('r');        /* restore text display*/
  200.    cursor(1);            /* restore cursor      */
  201. }
  202.  
  203.  
  204. /*-----------*/
  205. /*  M E N U  */
  206. /*-----------*/
  207.  
  208. int menu(m_menu, nu_main, nu_sub, hi_attr, nor_attr)
  209. struct menu_str m_menu[];
  210. int nu_main, nu_sub, hi_attr, nor_attr;
  211. {
  212.    extern unsigned int page;
  213.    extern unsigned int attribute;
  214.    extern unsigned int mon_type;
  215.  
  216.    int i, j, cur_x, cur_y, cur_opt, found, expert = 1;
  217.    char ch, ext, ltr;
  218.  
  219.    ch = ' ';
  220.    ext = ' ';
  221.    cur_opt = 0;
  222.    found = 0;
  223.  
  224.    if (mon_type == 1)
  225.       attribute = set_color(YELLOW, BLACK);
  226.    else
  227.       attribute = nor_attr;
  228.  
  229.    make_window(1, 1, 78, 1, 1);
  230.  
  231.    for (;;)               /* endless loop */
  232.       {
  233.       for (i = 0; i < nu_main; i++)
  234.          {
  235.          j = 0;
  236.          while (ltr = m_menu[i].head[j++])
  237.             {
  238.             if (ch == ltr && ch != ' ')
  239.                {
  240.                found = TRUE;
  241.                cur_opt = i;
  242.                }
  243.             }
  244.          }
  245.          if (ch == 13)
  246.             {
  247.             found = TRUE;
  248.             expert = FALSE;
  249.             }
  250.  
  251.          ch = ' ';
  252.          cur_x = 2;
  253.          cur_y = 2;
  254.  
  255.          for (i = 0; i < nu_main; i++)
  256.             {
  257.             if (i == cur_opt)
  258.                attribute = hi_attr;
  259.             else
  260.                attribute= nor_attr;
  261.             print(cur_x, cur_y, m_menu[i].head);
  262.             cur_x += strlen(m_menu[i].head) + 3;
  263.             }
  264.  
  265.          if (!expert)
  266.             found = TRUE;
  267.  
  268.          if (found)
  269.             {
  270.             ext = pull_down(m_menu, nu_sub, cur_opt); /* pull-down options */
  271.             if (ext == 27)
  272.                expert = TRUE;
  273.             if (ext == 'r' || ext == 'l')
  274.                expert = FALSE;
  275.             if (ext == 'r')
  276.                ++cur_opt;
  277.             if (ext == 'l')
  278.                --cur_opt;
  279.             ch = ' ';
  280.             ext = ' ';
  281.             }
  282.  
  283.             if (!found)
  284.                {
  285.                ch = ' ';
  286.                get_key(&ch, &ext);
  287.                ch = toupper(ch);
  288.                }
  289.  
  290.             if (ch == 27)
  291.                return;
  292.  
  293.             if (ext == 'r' || ext == 'l')
  294.                expert = 0;
  295.             if (ext == 'r')
  296.                ++cur_opt;
  297.             if (ext == 'l')
  298.                --cur_opt;
  299.             if (cur_opt >= nu_main)
  300.                cur_opt = 0;
  301.             if (cur_opt < 0)
  302.                cur_opt = nu_main - 1;
  303.             ext = ' ';
  304.             found = 0;
  305.  
  306.       }  /* end for (;;) */
  307. }
  308.  
  309.  
  310.  
  311. /*---------------------*/
  312. /*  P U L L _ D O W N  */
  313. /*---------------------*/
  314.  
  315. int pull_down(m_menu, nu_sub, position)
  316. struct menu_str m_menu[];
  317. int position;
  318. {
  319.    extern unsigned int page;
  320.    extern unsigned int attribute;
  321.    char ch = ' ', ltr;
  322.    int ext = ' ', hi_attr, nor_attr;
  323.    int i, j, tx, ty, start, width, nu_opt, cur_opt = 0, found = FALSE;
  324.  
  325.    nu_opt = nu_sub;
  326.  
  327.    /* nu_sub = number of possible pull-down options */
  328.    /* find out how many are in use */
  329.  
  330.    for (i = 0; i < nu_opt; i++)
  331.       {
  332.       if (m_menu[position].body[i][0] == '\0')
  333.          {
  334.          nu_opt = i;
  335.          break;
  336.          }
  337.       }
  338.  
  339.    if (mon_type == 1)
  340.       {
  341.       hi_attr = set_color(BLACK, CYAN);
  342.       nor_attr = set_color(WHITE, BLACK);
  343.       }
  344.    else
  345.       {
  346.       hi_attr = REVERSE;
  347.       nor_attr = NORMAL;
  348.       }
  349.  
  350.    attribute = nor_attr;
  351.  
  352.    start = 2;     /* Figure where to draw pull-down box */
  353.                   /* 2 is column to start 1st box */
  354.                   /* Add up length of menu heads */
  355.         
  356.    for (i = 0; i < position; i++)
  357.       start += strlen(m_menu[i].head) + 3;
  358.  
  359.    width = 0;     /* figure max length of window */
  360.  
  361.    for (i = 0; i < nu_opt; i++)
  362.       if (strlen(m_menu[position].body[i]) > width)
  363.          width = strlen(m_menu[position].body[i]);
  364.  
  365.    /* move box to left if it will spill off right side */
  366.  
  367.    if (start + width + 1 > 80)
  368.       start = 80 - width - 2;
  369.  
  370.    win_save('s');
  371.  
  372.    if (mon_type == 1)
  373.       attribute = set_color(YELLOW, BLACK);
  374.  
  375.    make_window(start++, 3, width, nu_opt, 0);   /*make a window */
  376.    attribute = nor_attr;
  377.  
  378.    tx = start;   /* reposition for writing */
  379.    ty = 4;
  380.  
  381.    for (;;)
  382.       {
  383.       for (i = 0; i < nu_opt; i++)
  384.          {
  385.          if (i == cur_opt)
  386.             attribute = hi_attr;
  387.          else
  388.             attribute = nor_attr;
  389.          print(tx, ty++, m_menu[position].body[i]);
  390.          }
  391.  
  392.       attribute = nor_attr;
  393.  
  394.       if (found)
  395.          {
  396.          win_save('r');     /* remove box */
  397.  
  398.          /* If you want more than 5 menu options */
  399.          /* change this next switch statement    */
  400.  
  401.          switch(cur_opt)    /* call function */
  402.             {
  403.             case 0: (*m_menu[position].fun1)(); break;
  404.             case 1: (*m_menu[position].fun2)(); break;
  405.             case 2: (*m_menu[position].fun3)(); break;
  406.             case 3: (*m_menu[position].fun4)(); break;
  407.             case 4: (*m_menu[position].fun5)(); break;
  408.             }
  409.  
  410.          /* found = FALSE; */
  411.          if (kbhit())
  412.             getch();  /* make sure keyboard buffer is clear */
  413.          return(' ');
  414.          }
  415.  
  416.          tx = start;
  417.          ty = 4;
  418.          get_key(&ch, &ext);  /* get a character */
  419.          ch = toupper(ch);
  420.          if (ext == 'd')
  421.             ++cur_opt;
  422.          if (ext == 'u')
  423.             --cur_opt;
  424.          if (cur_opt >= nu_opt)
  425.             cur_opt = 0;
  426.          if (cur_opt < 0)
  427.             cur_opt = nu_opt - 1;
  428.  
  429.          if (ch == 13)
  430.             found = TRUE;
  431.  
  432.          for (i = 0; i < nu_opt; i++)   /* does it match an option? */
  433.             {
  434.             j = 0;
  435.             while (ltr = m_menu[position].body[i][j++])
  436.                {
  437.                if (ch == ltr)
  438.                   {
  439.                   cur_opt = i;
  440.                   found = TRUE;
  441.                   }
  442.                }
  443.             }
  444.  
  445.          if (ext == 'l'|| ext == 'r')
  446.             break;
  447.  
  448.          if (ch == 27)   /* EXIT IF ESCAPE KEY */
  449.             {
  450.             ext = ch;
  451.             break;
  452.             }
  453.  
  454.          ext = ' ';
  455.          ch = ' ';
  456.  
  457.       }   /* end for (;;) */
  458.  
  459.    win_save('r');
  460.    return (ext);
  461. }
  462.  
  463.  
  464. /*---------------------*/
  465. /*  M A K E _ H E L P  */
  466. /*---------------------*/
  467.  
  468. void make_help()
  469. {
  470.    extern unsigned int page, attribute;
  471.  
  472.    page = 1;
  473.  
  474.    print( 1,  1, "Hello - This is a sample of an instant help screen.");
  475.    print(10,  5, "This screen was printed to the second page of graphics");
  476.    print(10,  7, "while you were looking at the main menu.");
  477.    print(10,  9, "This help screen can be left undisturbed");
  478.    print(10, 11, "and redisplayed at any time.");
  479.    print( 1, 20, "Please touch any key to return to the main menu.");
  480.  
  481.    page = 0;
  482. }
  483.  
  484.  
  485. /*---------------------*/
  486. /*  M A K E _ I N S T  */
  487. /*---------------------*/
  488.  
  489. void make_inst()
  490. {
  491.    extern unsigned int attribute;
  492.  
  493.    if (mon_type == 1)
  494.       attribute = set_color(GREEN, BLACK);
  495.    else
  496.       attribute = NORMAL;
  497.  
  498.    print( 1,  4, "INSTRUCTIONS:");
  499.    print( 1,  6, "EXPERT MODE: Select by touching the key which represents each option.");
  500.    print(15,  7, "(the capital letter)");
  501.  
  502.    print( 1, 10, "ASSIST MODE: Pull-down menu by touching 'enter' or a cursor key.");
  503.    print(14, 11, "Select by highlighting with cursor keys- then touch return");
  504.    print(14, 13, "Return to Expert mode by touching 'escape'");
  505.  
  506.    print( 1, 15, "EXIT:        Touch 'Escape' while in expert mode.");
  507. }
  508.  
  509.  
  510. /*---------------------*/
  511. /*  M O N O _ H E L P  */
  512. /*---------------------*/
  513.  
  514. void mono_help()
  515. {
  516.    attribute = NORMAL;
  517.    win_save('s');
  518.  
  519.    clear_window(1, 4, 80, 21);
  520.    print(1,  7, "This is a demonstration of a help screen.");
  521.    print(1,  9, "This text was written by means of direct memory address.");
  522.    print(1, 10, "The original screen has been saved and will be restored ");
  523.    print(1, 11, "when you exit this 'help' screen.");
  524.    print(1, 14, "Please touch any key to continue.");
  525.  
  526.    getch();
  527.    win_save('r');
  528. }
  529.  
  530.  
  531. /*-----------*/
  532. /*  D E M O  */
  533. /*-----------*/
  534.  
  535. void demo()
  536. {
  537.    win_save('s');
  538.    make_window(20, 10, 40, 5, 1);
  539.  
  540.    print(21, 11, "Put your favorite routine here ");
  541.    print(21, 14, "touch any key to return to menu");
  542.    getch();
  543.  
  544.    win_save('r');
  545. }
  546.  
  547.  
  548. /*-----------*/
  549. /*  H E L P  */
  550. /*-----------*/
  551.  
  552. void help()
  553. {
  554.    if (mon_type == 1)     /* If color card flip page to */
  555.       {
  556.       page = 1;           /* Show text else write to current screen */
  557.       d_page();
  558.       getch();
  559.       page = 0;
  560.       d_page();
  561.       }
  562.    else
  563.       mono_help();
  564. }
  565.  
  566.  
  567.          /* Screen Function Library */
  568.  
  569. /*
  570. **  Declare the extern variables page, attribute, and 
  571. **  mon_type (monitor type) in your main program.
  572. */
  573.  
  574.  
  575. /*---------------*/
  576. /*  G O T O X Y  */
  577. /*---------------*/
  578.  
  579. void gotoxy(x, y)    /* Puts cursor at x,y position on selected page */
  580. unsigned int x, y;   /* 1,1 is upper left corner */
  581. {
  582.    extern unsigned int page;
  583.    union REGS regist;
  584.  
  585.    if (x < 1 || x > 80)
  586.       return;
  587.    if (y < 1 || y > 25)
  588.       return;
  589.    --x;
  590.    --y;                  /* BIOS starts coordinates at 0,0 */
  591.  
  592.    regist.h.ah = 0x02;
  593.    regist.x.dx = (y << 8) | x;
  594.    regist.h.bh = page;
  595.    int86(0x10, ®ist, ®ist);
  596. }
  597.  
  598.  
  599. /*-----------------*/
  600. /*  W H E R E X Y  */
  601. /*-----------------*/
  602.  
  603. int wherexy(x, y)  /* Returns the x,y position of cursor */
  604. int *x, *y;
  605. {
  606.    extern unsigned int page;
  607.    union REGS regist;
  608.  
  609.    regist.h.ah = 0x03;
  610.    regist.h.bh = page;
  611.    int86(0x10, ®ist, ®ist);
  612.    *x = regist.h.dl + 1;
  613.    *y = regist.h.dh + 1;
  614. }
  615.  
  616.  
  617. /*---------------*/
  618. /*  D _ P A G E  */
  619. /*---------------*/
  620.  
  621. /* Displays the page indicated by extern var page */
  622. /* Use only with color card */
  623.  
  624. void d_page()
  625. {
  626.    extern unsigned int page;
  627.    union REGS regist;
  628.  
  629.    regist.h.ah = 0x05;
  630.    regist.h.al = page;
  631.    int86(0x10, ®ist,®ist);
  632. }
  633.  
  634.  
  635. /*-------------------*/
  636. /*  W I N _ S A V E  */
  637. /*-------------------*/
  638.  
  639. void win_save(action)               /* Saves or restores primary  */
  640. int action;                         /* display screen.            */
  641. {                                   /* (page 0 for color display) */
  642.    extern unsigned int page;        /*   's' = save               */
  643.    extern unsigned int mon_type;    /*   'r' = restore            */
  644.    int position;                    /* Saves cursor position too  */
  645.    static int ptr;                  /* May make snow on CGA       */
  646.  
  647.    static struct
  648.    {
  649.       int x;
  650.       int y;
  651.       unsigned int buffer[4000];
  652.    }
  653.       window[2];
  654.  
  655.  
  656.    if (mon_type == 1)
  657.       position = 0xB800;  /* Color card */
  658.    else
  659.       position = 0xB000;  /* Monochrome */
  660.  
  661.    if (action == 's')     /* save */
  662.       {
  663.       if (ptr > 1)
  664.          {
  665.          ptr = 2;
  666.          return;
  667.          }
  668.  
  669.       /*
  670.       **  Note:  I used movedata because the peek function is specific
  671.       **         to Lattice C.
  672.       **
  673.       **  peek(position, 0x00, &window[ptr].buffer, 4000);
  674.       **
  675.       **  Also see poke below.
  676.       */
  677.  
  678.       /* save screen */
  679.       movedata(position, 0, _DS, (int)&window[ptr].buffer, 4000);
  680.  
  681.       /* save cursor location */
  682.       wherexy(&window[ptr].x, &window[ptr].y);
  683.       ptr++;
  684.       }
  685.  
  686.    if (action == 'r')   /* restore */
  687.       {
  688.       if (ptr < 1)
  689.          {
  690.          ptr = 0;
  691.          return;
  692.          }
  693.       --ptr;
  694.  
  695.       /* poke(position, 0, &window[ptr].buffer, 4000); */
  696.  
  697.       /* restore screen */
  698.       movedata(_DS, (int)&window[ptr].buffer, position, 0, 4000);
  699.  
  700.       /* restore cursor location */
  701.       gotoxy(window[ptr].x, window[ptr].y);
  702.       }
  703. }
  704.  
  705.  
  706.  
  707. /*---------------------*/
  708. /*  S E T _ C O L O R  */
  709. /*---------------------*/
  710.  
  711. /* Call with foreground and background colors.  Returns attribute. */
  712.  
  713. int set_color(foreground, background)
  714. int foreground,background;
  715. {
  716.    return (background << 4 | foreground);
  717. }
  718.  
  719.  
  720.  
  721. /*---------------------------*/
  722. /*  C L E A R _ W I N D O W  */
  723. /*---------------------------*/
  724.  
  725. void clear_window(x, y, width, height)  /* Call with x,y of upper left   */
  726. unsigned int x, y, width, height;       /* corner of window area.        */
  727. {                                       /* Clears down and to right      */
  728.    extern unsigned int page;            /* for width and height.         */
  729.    extern unsigned int attribute;       /* Cleared with active attribute */
  730.    union REGS regist;                   /* Use on displayed page only!   */
  731.  
  732.    regist.x.ax = 0x0600;
  733.    regist.h.ch = --y;
  734.    regist.h.cl = --x;
  735.    regist.x.dx = (y + height - 1) << 8 | x + width - 1;
  736.    regist.h.bh = attribute;
  737.    int86(0x10, ®ist, ®ist);
  738. }
  739.  
  740.  
  741. /*---------*/
  742. /*  B O X  */
  743. /*---------*/
  744.  
  745. void box(x, y, width, height, type)    /* type 0 = pull-down box */
  746. int x, y, width, height, type;         /* type 1 = regular box   */
  747. {
  748.    int i, u_right, u_left;
  749.    char string[82];
  750.  
  751.    if (type == 0)           /* following sets corners */
  752.       {
  753.       u_left  = '\xC2';
  754.       u_right = '\xC2';
  755.       }
  756.    else if (type == 1)
  757.       {
  758.       u_left  = '\xDA';
  759.       u_right = '\xBF';
  760.       }
  761.  
  762.    string[0] = u_left;
  763.    for (i = 1; i <= width; string[i++] = '\xC4');
  764.    string[i++] = u_right;
  765.    string[i] = '\0';
  766.    print(x, y++, string);
  767.  
  768.    for (i = 0; i < height; i++)
  769.       {
  770.       print(x, y, "\xB3");
  771.       print(x + width + 1, y++, "\xB3");
  772.       }
  773.  
  774.    string[0]='\xC0';
  775.    for(i = 1; i <= width; string[i++] = '\xC4');
  776.    string[i++] = '\xD9';
  777.    string[i] = '\0';
  778.    print(x, y++, string);
  779. }
  780.  
  781.  
  782. /*-------------------*/
  783. /*  W H A T _ M O N  */
  784. /*-------------------*/
  785.  
  786. int what_mon()  /* Returns a 1 if color card present, 0 if monochrome */
  787. {
  788.    return (peekb(0x0040, 0x0049) != 7);
  789. }
  790.  
  791.  
  792. /*---------*/
  793. /*  C L S  */
  794. /*---------*/
  795.  
  796. void cls()  /* Same as DOS cls */
  797. {
  798.    clear_window(1, 1, 80, 25);
  799.    gotoxy(1, 1);
  800. }
  801.  
  802.  
  803. /*-------------------------*/
  804. /*  M A K E _ W I N D O W  */
  805. /*-------------------------*/
  806.  
  807. void make_window(x, y, width, height, type)  /* Draws and clears a box */
  808. unsigned int x, y, width, height, type;
  809. {
  810.    box(x++, y++, width, height, type);    /* Draw box */
  811.    clear_window(x, y, width, height);     /* Clear interior */
  812. }
  813.  
  814.  
  815. /*---------------*/
  816. /*  C U R S O R  */
  817. /*---------------*/
  818.  
  819. int cursor(size)    /* Sets cursor size */
  820. int size;           /* 0 = no cursor, 1 = normal, 2 = big cursor */
  821. {
  822.    union REGS regist;
  823.  
  824.    regist.h.ah = 0x01;
  825.  
  826.    if (mon_type == 1 )                /* color */
  827.       {
  828.       if (size == 0)
  829.          regist.x.cx = 0x0F0F;
  830.       else if (size == 1)
  831.          regist.x.cx = 0x0607;
  832.       else if (size == 2)
  833.          regist.x.cx = 0x0107;
  834.       }
  835.    else                               /* monochrome */
  836.       {
  837.       if (size == 0)
  838.          regist.x.cx = 0x0F0F;
  839.       else if (size == 1)
  840.          regist.x.cx = 0x0C0D;
  841.       else if (size == 2)
  842.          regist.x.cx = 0x010D;
  843.       }
  844.  
  845.    int86(0x10, ®ist, ®ist);
  846. }
  847.  
  848.  
  849. /*-------------*/
  850. /*  P R I N T  */
  851. /*-------------*/
  852.  
  853. void print(x, y, str)        /* A switcher - routes to fast_write */
  854. unsigned int x, y;           /* or to dos_prt depending on argv   */
  855. char *str;                   /* passed to program and stored in   */
  856. {                            /* extern char wr_meth               */
  857.    extern char wrt_meth;
  858.  
  859.    if (wrt_meth == 'f')        /* Fast (direct poking) */
  860.       fast_write(x, y, str);
  861.    else if (wrt_meth == 's')   /* Slow (DOS method) */
  862.       {
  863.       gotoxy(x, y);
  864.       dos_prt(str);
  865.       }
  866. }
  867.  
  868.                             
  869. /*-----------------*/    /*  Asks DOS to write a string with attribute    */
  870. /*  D O S _ P R T  */    /*  defined.  an alternative to fast write in    */
  871. /*-----------------*/    /*  that it is "well behaved" (goes through DOS) */
  872.                          /*  Specify page and set cursor position before  */
  873. void dos_prt(str)        /*  calling */
  874. char *str;                  
  875. {
  876.    extern unsigned int page, attribute;
  877.    unsigned int x, y;
  878.    union REGS regist;
  879.  
  880.    wherexy(&x, &y);
  881.    while (*str)
  882.       {
  883.       if (x > 80)
  884.          {
  885.          x = 1;
  886.          ++y;
  887.          }
  888.       if (y > 25)
  889.          break;
  890.       gotoxy(x++, y);
  891.       regist.x.bx = (page << 8 | attribute);
  892.       regist.x.cx = 1;
  893.       regist.x.ax = 0x0900 | *str++;
  894.       int86(0x10, ®ist, ®ist);
  895.       }
  896.    gotoxy(x, y);     /* put cursor at end of string */
  897. }
  898.  
  899.  
  900. /*-----------------------*/
  901. /*  F A S T _ W R I T E  */
  902. /*-----------------------*/
  903.  
  904. void fast_write(x, y, string)    /* Directly pokes string at x,y position */
  905. int x, y;                        /* Uses attribute and page.              */
  906. char *string;                    /* May cause snow on some graphic cards  */
  907. {
  908.    extern unsigned int page;
  909.    extern unsigned int attribute;
  910.    extern unsigned int mon_type;   /* Monitor type */
  911.    int position, offset, orig;
  912.  
  913.    if (page <= 3 && page >= 0)
  914.       offset = 4000 * page + 96 * page;
  915.    orig = offset;
  916.    offset += (y-1) * 160 + 2 * (x-1);
  917.    if (mon_type == 0)
  918.       position = 0xB000;
  919.    else
  920.       position = 0xB800;
  921.  
  922.    while (*string)
  923.       {
  924.       pokeb(position, offset, *string++);          /* Poke character */
  925.       pokeb(position, offset+1, (char)attribute);  /* Poke attribute */
  926.       offset += 2;
  927.       }
  928.    offset -= orig;                /* Figure where I am */
  929.    x = (offset % 160) / 2 + 1;
  930.    y = offset / 160 + 1;          /* and move cursor   */
  931.    gotoxy(x, y);
  932. }
  933.  
  934.  
  935. /*-----------------*/
  936. /*  G E T _ K E Y  */
  937. /*-----------------*/
  938.  
  939. int get_key(ch, ext)          /* Read a char             */
  940. char *ch;                     /* Return character in ch  */
  941. int *ext;                     /* If it is a function key */
  942. {                             /* return following in ext */
  943.    *ch = getch();             /*   up-arrow    = 'u'     */
  944.    if (!*ch)                  /*   down-arrow  = 'd'     */
  945.       {                       /*   right-arrow = 'r'     */
  946.       *ext = getch();         /*   left-arrow  = 'l'     */
  947.       switch (*ext)
  948.          {
  949.          case 'H': *ext = 'u'; break;  /*  up      */
  950.          case 'P': *ext = 'd'; break;  /*  down    */
  951.          case 'M': *ext = 'r'; break;  /*  right   */
  952.          case 'K': *ext = 'l'; break;  /*  left    */
  953.          case 'G': *ext = 'h'; break;  /*  home    */
  954.          case 'O': *ext = 'e'; break;  /*  end     */
  955.          case 'R': *ext = 'I'; break;  /*  insert  */
  956.          case 'S': *ext = 'D'; break;  /*  delete  */
  957.          }
  958.       }
  959. }
  960.